#include <wdm.h>

#include "mydriver.h"

NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath)
{
	NTSTATUS status = STATUS_SUCCESS;
	PDEVICE_OBJECT p_device_object = NULL;
	UNICODE_STRING driver_name, dos_driver_name;
	
	UNREFERENCED_PARAMETER(pRegistryPath);
	
	DbgPrint("DriverEntry called\r\n");
	
	RtlInitUnicodeString(&driver_name, DRVNAME);
	RtlInitUnicodeString(&dos_driver_name, DOSDRVNAME);
	
	status = IoCreateDevice(pDriverObject, 0, &driver_name, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &p_device_object);

	if (!NT_SUCCESS(status)) return status;

	pDriverObject->MajorFunction[IRP_MJ_CREATE] = CreateMyDriver;
	pDriverObject->MajorFunction[IRP_MJ_CLOSE] = CloseMyDriver;
	pDriverObject->MajorFunction[IRP_MJ_WRITE] = WriteMyDriver;
	pDriverObject->DriverUnload = UnloadMyDriver;
	
	p_device_object->Flags |= DO_DIRECT_IO;
	p_device_object->Flags &= (~DO_DEVICE_INITIALIZING);
	
	status = IoCreateSymbolicLink(&dos_driver_name, &driver_name);
	
	if (!NT_SUCCESS(status)) IoDeleteDevice(pDriverObject->DeviceObject);
	
	return status;
}

NTSTATUS CreateMyDriver(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
{
	UNREFERENCED_PARAMETER(pDeviceObject);
	UNREFERENCED_PARAMETER(pIrp);
	PAGED_CODE();

	DbgPrint("CreateMyDriver called\r\n");
	
	InbvEnableBootDriver(TRUE);
	InbvAcquireDisplayOwnership();
	InbvResetDisplay();
	InbvSolidColorFill(0, 0, 639, 479, 4);
	InbvSetTextColor(15);
	InbvInstallDisplayStringFilter(NULL);
	InbvEnableDisplayString(TRUE);
	InbvSetScrollRegion(0, 0, 639, 479);
	
	return STATUS_SUCCESS;
}

NTSTATUS CloseMyDriver(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
{
	UNREFERENCED_PARAMETER(pDeviceObject);
	UNREFERENCED_PARAMETER(pIrp);
	PAGED_CODE();

	DbgPrint("CloseMyDriver called\r\n");
	
	return STATUS_SUCCESS;
}

NTSTATUS WriteMyDriver(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
{
	PIO_STACK_LOCATION pIoStackIrp = NULL;
	PUCHAR pWriteDataBuffer;
	
	UNREFERENCED_PARAMETER(pDeviceObject);
	PAGED_CODE();
	
	DbgPrint("WriteMyDriver called\r\n");
	
	pIoStackIrp = IoGetCurrentIrpStackLocation(pIrp);
	if (pIoStackIrp)
	{
		pWriteDataBuffer = MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority);
		if (pWriteDataBuffer)
		{
			if (IsStringTerminated(pWriteDataBuffer, pIoStackIrp->Parameters.Write.Length))
			{
				InbvDisplayString(pWriteDataBuffer);
			}
		}
	}
	
	return STATUS_SUCCESS;
}

VOID UnloadMyDriver(PDRIVER_OBJECT pDriverObject)
{
	UNICODE_STRING dos_driver_name;

	PAGED_CODE();

	DbgPrint("UnloadMyDriver called\r\n");
	RtlInitUnicodeString(&dos_driver_name, DOSDRVNAME);
	IoDeleteSymbolicLink(&dos_driver_name);
	
	IoDeleteDevice(pDriverObject->DeviceObject);
}

BOOLEAN IsStringTerminated(PUCHAR pString, ULONG length)
{
	BOOLEAN terminated = FALSE;
	ULONG index = 0;

	PAGED_CODE();
	
	while (index < length && terminated == FALSE)
	{
		if (pString[index] == '\0') terminated = TRUE;
		else ++index;
	}
	
	return terminated;
}